﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Threading;
using Helper;
using WpfControls;
using Forms = System.Windows.Forms;

namespace FileRenamer
{

	/// <summary>
	/// Interaction logic for Window1.xaml
	/// </summary>
	public partial class Window1 : Window
	{
		[STAThread]
		static void Main()
		{
			Application app = new Application();
			app.Run(new Window1());
		}

		#region Private Fields
		private FileRenamerSystem FRSystem;
		private Forms.FolderBrowserDialog dlgFolder;
		private const string permaExclude = ".ini,.db,.exe";
		private bool dontChangeTabFlag;
		#endregion

		#region Main Windows Methods
		public Window1()
		{
			InitializeComponent();
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			Globals.WindowLocation = new Point(this.Left, this.Top);
			if (!Directory.Exists(Globals.AppDataFolder)) Directory.CreateDirectory(Globals.AppDataFolder);
			if (!Directory.Exists(Globals.ExtensionFolder)) Directory.CreateDirectory(Globals.ExtensionFolder);
			
			Globals.Settings = Settings.LoadSettings() ?? new Settings();
			txtPath.Text = Globals.Settings.FolderPath;
			chkRYes.IsChecked = Globals.Settings.Recursive;
			
			FRSystem = new FileRenamerSystem();
			FRSystem.ErrorAdded += new ErrorAddedHandler(FRSystem_ErrorAdded);
			FRSystem.WorkOperationComplete += new WorkOperationCompleteHandler(FRSystem_WorkOperationComplete);
			FRSystem.ProgressChanged += new ProgressChangedHandler(FRSystem_ProgressChanged);

			loadExtensions();
			txtExpression.auto_List = Globals.Commands.CommandNames();

			txtPath.Text = Globals.Settings.FolderPath;
			chkRYes.IsChecked = Globals.Settings.Recursive;
			mnuExtensions_EnableExtensions.IsChecked = Globals.Settings.EnableExtensions;
			txtAppendText_TextChanged(txtAppendText, null);
		}

		private void Window_Closing(object sender, CancelEventArgs e)
		{
			Globals.Settings.Save();
		}

		private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
		{
			if (e.Key == System.Windows.Input.Key.Escape) this.Close();
		}

		private void Window_LocationChanged(object sender, EventArgs e)
		{
		}

		private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
		{
		}

		/// <summary>
		/// Error expander has been expanded
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void expError_Expanded(object sender, RoutedEventArgs e)
		{
			expError.Foreground = Brushes.Black;
			this.Height += 130;
			fileList.Margin = new Thickness(fileList.Margin.Left, fileList.Margin.Top + 130, fileList.Margin.Right, fileList.Margin.Bottom);
		}

		/// <summary>
		/// Error expander has been collapsed
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void expError_Collapsed(object sender, RoutedEventArgs e)
		{
			expError.Foreground = Brushes.Black;
			this.Height -= 130;
			fileList.Margin = new Thickness(fileList.Margin.Left, fileList.Margin.Top - 130, fileList.Margin.Right, fileList.Margin.Bottom);
		}

		#region Main Menu
		private void mnuExtensions_EnableExtensions_Click(object sender, RoutedEventArgs e)
		{
			Globals.Settings.EnableExtensions = mnuExtensions_EnableExtensions.IsChecked;
			Globals.Settings.Save();
		}

		private void mnuExtensions_ExtensionManager_Click(object sender, RoutedEventArgs e)
		{
			new ExtensionManager().ShowDialog();
		}
		#endregion

		#endregion

		#region loadExtensions
		private void loadExtensions()
		{
			Globals.Commands = new Commands();

			foreach (ICommand c in Globals.Commands)
			{
				Grid tabContent = new Grid();
				string header = c.LoadXaml(ref tabContent);
				if (String.IsNullOrEmpty(header)) continue;
				TabItem tab = new TabItem();
				tab.Header = header;
				tab.Name = "ext_tab_" + c.CommandName;
				tab.Content = tabContent;
				tbcOptions.Items.Add(tab);
			}
		}
		#endregion

		#region browse
		private void btnBrowse_Click(object sender, RoutedEventArgs e)
		{
			dlgFolder = new Forms.FolderBrowserDialog();
			dlgFolder.Description = "Select a Folder: ";
			dlgFolder.SelectedPath = !String.IsNullOrEmpty(txtPath.Text) && !Directory.Exists(txtPath.Text) ?
				Environment.GetFolderPath(Environment.SpecialFolder.MyMusic) : txtPath.Text;
			dlgFolder.ShowDialog();
			txtPath.Text = dlgFolder.SelectedPath;
		}
		#endregion

		#region update Session
		private ListOfFiles.SessionData getSession()
		{
			ListOfFiles.SessionData data = new ListOfFiles.SessionData();

			data.RootPath = txtPath.Text;
			data.OnlyExt = new List<string>();
			data.ExcludeExt = new List<string>();
			data.SearchPatturn = String.IsNullOrEmpty(txtFileNameSearch.Text) ? "*" : txtFileNameSearch.Text;
			data.Mode = ((TabItem)tbcOptions.SelectedItem).Name;
			data.Recursive = chkRYes.IsChecked.Value;
			data.Order = radSortAsc.IsChecked.Value ? ListOfFiles.Order.Asc : ListOfFiles.Order.Desc;
			if (radSortAccessed.IsChecked.Value) data.SortBy = FileRenamer.ListOfFiles.FileCompareOptions.LastAccessTime;
			else if (radSortCreateDate.IsChecked.Value) data.SortBy = ListOfFiles.FileCompareOptions.CreateDate;
			else if (radSortLength.IsChecked.Value) data.SortBy = ListOfFiles.FileCompareOptions.Length;
			else if (radSortModified.IsChecked.Value) data.SortBy = ListOfFiles.FileCompareOptions.LastWriteTime;
			else if (radSortName.IsChecked.Value) data.SortBy = ListOfFiles.FileCompareOptions.FileName;
			else if (radSortExtension.IsChecked.Value) data.SortBy = ListOfFiles.FileCompareOptions.Extension;

			data.Regex = txtRegex.Text;
			data.RegexReplace = txtRegexReplace.Text;

			//--Build extension lists--//
			String[] arrayOnly = txtIncludeExt.Text.Replace(" ", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			String[] arrayExclude = txtExcludeExt.Text.Replace(" ", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (String s in arrayOnly) data.OnlyExt.Add(s);
			foreach (String s in arrayExclude) data.ExcludeExt.Add(s);
			//--//

			string[] permas = permaExclude.Split(',');
			foreach (string p in permas) data.ExcludeExt.Add(p);

			return data;
		}
		#endregion

		#region btnGetFiles_Click
		private void btnGetFiles_Click(object sender, RoutedEventArgs e)
		{
			if (Directory.Exists(txtPath.Text))
			{
				Cursor = Cursors.Wait;
				ListOfFiles.SessionData sessionData = getSession();

				fileList.DataContext = null;
				expError.Foreground = Brushes.Black;

				prbProgress.Value = 0;

				FRSystem.GetFiles(sessionData, lblCommandText.Content.ToString());
			}
			else
			{
				FRSystem_ErrorAdded(null, new Events.MessageArgs("Directory does not exist: " + txtPath.Text));
				myStoryboard.Stop(grdContent);
			}
		}

		#endregion

		#region progressChanged
		private void FRSystem_ProgressChanged(object sender, Events.MessageArgs e)
		{
			lblCurrentFile.Content = e.Message;
		}
		#endregion

		#region operationComplete - reload list & stop animations
		private void FRSystem_WorkOperationComplete(object sender, Events.GetFilesCompleteArgs e)
		{
			myStoryboard.Stop(grdContent);
			myStoryboard2.Stop(grdContent);
			myStoryboard3.Stop(grdContent);
			fileList.DataContext = null;
			fileList.DataContext = e.ListOfFiles;
			lblCurrentFile.Content = "";
			btnGetFiles.BitmapEffect = null;
			Cursor = Cursors.Arrow;
			btnRename.IsEnabled = true;
			btnUndo.IsEnabled = true;
		}
		#endregion

		#region txtNew TextChanged - Update Tooltip
		void txtNew_TextChanged(object sender, TextChangedEventArgs e)
		{
			TextBox s = (TextBox)sender;
			//int x = s.SelectionStart;
			//s.Text = ReplaceInvalidChars(s.Text);
			//if (x > 0)
			//s.SelectionStart = x - 1;
			if (s.ToolTip != null)
			{
				s.ToolTip = FileRenamerSystem.GetFilePath(s.ToolTip.ToString()) + s.Text;
				String f = s.Tag.ToString();
				FRSystem.UpdateNewFileName(f, s.ToolTip.ToString());
			}
		}
		#endregion

		#region btnRename_Click
		private void btnRename_Click(object sender, RoutedEventArgs e)
		{
			Cursor = Cursors.Wait;
			btnRename.IsEnabled = false;
			FRSystem.RenameFiles();
		}
		#endregion

		#region removeItem Events
		private void removeItem_Click(object sender, RoutedEventArgs e)
		{
			Button b = (Button)sender;

			removeFromList(b.Tag.ToString());
		}
		private void mnuRemove_Click(object sender, RoutedEventArgs e)
		{
			FileToRename[] files = new FileToRename[fileList.SelectedItems.Count];
			fileList.SelectedItems.CopyTo(files, 0);
			int count = fileList.SelectedItems.Count;
			for(int i = 0; i < count; i++)
			{
				removeFromList(files[i].FullFileName);
			}
		}

		#endregion

		#region Remove Item From List & and Add to Exclude List
		private void removeFromList(String fullName)
		{
			fileList.DataContext = null;
			fileList.DataContext = FRSystem.RemoveFromList(fullName);
		}

		#endregion

		#region Clear Exclude List
		private void btnClearExcludeList_Click(object sender, RoutedEventArgs e)
		{
			FRSystem.ClearExcludeList();
		}
		#endregion

		#region Undo Click
		private void btnUndo_Click(object sender, RoutedEventArgs e)
		{
			FRSystem.UndoRename();
		}
		#endregion

		#region AddToErrorList
		private void FRSystem_ErrorAdded(object sender, Events.MessageArgs e)
		{
			Dispatcher.BeginInvoke(DispatcherPriority.Background,
				 (SendOrPostCallback)delegate { unSafeAddToErrorList(e.Message); }, null);
		}

		private void unSafeAddToErrorList(String message)
		{
			lstErrors.Items.Add(message);
			if (!expError.IsExpanded) expError.Foreground = Brushes.Red;
		}

		#endregion

		#region Change root path and heuristic for choosing options

		#region txtPath_TextChanged
		private void txtPath_TextChanged(object sender, TextChangedEventArgs e)
		{
			if (Directory.Exists(txtPath.Text))
			{
				txtPath.BitmapEffect = new OuterGlowBitmapEffect() { GlowColor = Colors.Green, GlowSize = 1, Opacity = .9 };
				
				BackgroundWorker worker = new BackgroundWorker();
				worker.DoWork += DoCrazyStuff;
				worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CrazyStuff_Complete);

				//needs lots of work, so for now ignore it
				//worker.RunWorkerAsync(txtPath.Text);
			}
			else
				txtPath.BitmapEffect = new OuterGlowBitmapEffect() { GlowColor = Colors.Red, GlowSize = 2, Opacity = .9 };
		}
		#endregion

		#region session struct
		private struct DoWork
		{
			public string Root;
			public bool Recurssive;
			public string ExcludeExt;
			public string IncludeExt;
			public string Mode;
			public EFiles Extensions;
			public bool Incremented;
			public string Text;
			public int StartPosition;
			public int Length;
			public string FirstFile;
		}
		#endregion

		#region Start Crazy Stuff
		private void DoCrazyStuff(object o, DoWorkEventArgs args)
		{
			DoWork data = new DoWork();
			String p = (string)args.Argument;
			
			DirectoryInfo d = new DirectoryInfo(p);
			data.Root = d.Name;

			FileInfo[] files = d.GetFiles();
			DirectoryInfo[] directories = d.GetDirectories();

			string[] tempExt = permaExclude.Split(',');
			List<string> blockExt = new List<string>();
			foreach (string b in tempExt)blockExt.Add(b);
			blockExt.Add("");
			blockExt.Add(".lnk");

			if (directories.Length > files.Length * .2)
			{
				data.Recurssive = true;
				files = HFile.GetAllFiles(p, -1, null, blockExt, null, 50).ToArray();
			}
			else
			{
				data.Recurssive = false;
				files = HFile.GetAllFiles(p, 1, null, blockExt, null, 50).ToArray();
			}

			int max = Math.Min(files.Length, 50);
			List<string> fileList = new List<string>();
			List<string> extList = new List<string>();
			for (int i = 0; i < max; i++)
			{
				if (fileBlock(files[i], blockExt))
				{
					extList.Add(files[i].Extension.ToLower());
					fileList.Add(files[i].Name.ToLower());
				}
			}
			doExtensionLogic(extList, fileList.Count, ref data);
			DoFileNameLogic(fileList, ref data);
			args.Result = data;
		}
		#endregion

		#region exclude certain filetypes
		private bool fileBlock(FileInfo file, ICollection<string> blockExt)
		{
			return !blockExt.Contains(file.Extension);
		}

		#endregion

		#region ExtensionLogic
		private void doExtensionLogic(List<string> extList, int total, ref DoWork data)
		{
			EFiles files = new EFiles();
			foreach (string s in extList)
			{
				if (!files.ContainsExt(s))
				{
					files.Add(new eFile(s, 1));
				}
				else
				{
					files[files.IndexOfExt(s)].Value++;
				}
			}
			files.GroupLike();
			files.SortValues();

			string only = "";
			int onlyCount = 0;
			string exclude = permaExclude + ",";
			int excludeCount = 0;
			float percent = (float) files[0].Value/(float) total;
			if (percent > .50)
			{
				only = files[0].Ext;
				onlyCount = 1;
				exclude = "";
			}
			else if (percent > .40)
			{
				only = files[0].Ext + "," + files[1].Ext;
				onlyCount = 2;
				for (int i = 2; i < files.Count; i++)
					if ((float)files[i].Value / (float)total < .1 && !exclude.Contains(files[i].Ext))
						exclude += files[i].Ext + ",";
			}
			else
			{
				for (int i = 0; i < Math.Min(files.Count, 4); i++)
					if (!exclude.Contains(files[i].Ext))
					{
						only += files[i].Ext + ",";
						onlyCount++;
					}
			}

			excludeCount = HBasic.CharCount(',', exclude);
			if (excludeCount > 4) exclude = "";
			else if (only.Length > 16) only = "";

			data.ExcludeExt = exclude;
			data.IncludeExt = only;
			data.Extensions = files;
		}

		#endregion

		#region FileNameLogic
		private void DoFileNameLogic(List<string> list, ref DoWork data)
		{
			List<string> small = new List<string>();
			for (int i = 0; i < list.Count; i++) 
				if (data.Extensions[0].Ext == HFile.GetExtension(list[i]))
					small.Add(list[i]);
			data.FirstFile = small.Count > 0 ? small[0] : "";

			List<char> sep = new List<char>() { ' ', '.', '-', '_' };
			int start = 0;
			int[] distances = new int[small.Count - 1];
			for (int i = 0; i < small.Count - 1; i++)
			{
				if (data.Extensions[0].Ext.ToLower() == ".mp3")
				{
					string inc = small[i].Substring(0, Math.Min(small[i].IndexOfAny(sep.ToArray()), Math.Min(4, small[i].Length)));
					string inc2 = small[i + 1].Substring(0, Math.Min(small[i + 1].IndexOfAny(sep.ToArray()), Math.Min(4, small[i + 1].Length)));
					distances[i] = HBasic.LDistance(inc, inc2);
					start = HBasic.Max(start,inc.Length,inc2.Length);
				}
			}
			double mean = HMath.Mean(distances);
			int length = 0;
			if (mean < 2 && data.Extensions[0].Ext.ToLower() == ".mp3")
			{
				data.Incremented = true;
				for (int i = start+1; i < small[0].Length - 1; i++)
				{
					if (small[0][i] == small[1][i]) length++;
					else break;
				}
			}
			else
			{
				data.Incremented = false;
				for (int i = 0; i < small[0].Length - 1; i++)
				{
					if (small[0][i] != small[0][i + 1]) start++;
					else if (small[0][i] == small[0][i + 1]) length++;
					else break;
				}
			}
			if (length < 4 && data.Incremented)
			{
				if (sep.Contains(small[0][start + 1])) start++;
				data.Mode = "tabRemove";
				data.StartPosition = 0;
				data.Length = start + 1;
			}
			else if (length >= 4)
			{
				data.Mode = "tabReplace";
				data.Text = small[0].Substring(start, length);
			}
			else if (length < 4)
			{
				data.Mode = "tabAppend";
			}
		}
		#endregion

		#region CrazyStuff_Complete
		void CrazyStuff_Complete(object sender, RunWorkerCompletedEventArgs e)
		{
			DoWork data = (DoWork)e.Result;
			chkRYes.IsChecked = data.Recurssive;
			txtExcludeExt.Text = data.ExcludeExt;
			txtIncludeExt.Text = data.IncludeExt;
			txtFirstFileName.Text = data.FirstFile;
			if (data.Mode == "tabRemove")
			{
				if (!dontChangeTabFlag) tbcOptions.SelectedItem = tabRemove;
				txtRemoveCount.Text = data.Length.ToString();
				txtRemoveIndex.Text = data.StartPosition.ToString();
			}
			else if (data.Mode == "tabReplace")
			{
				if (!dontChangeTabFlag) tbcOptions.SelectedItem = tabReplace;
				txtReplaceNew.Text = "";
				//txtReplaceOld.Text = data.text;
			}
			else if (data.Mode == "tabAppend")
			{
				if (!data.Root.Contains(":"))
					txtAppendText.Text = data.Root + "-";
				if (!dontChangeTabFlag) tbcOptions.SelectedItem = tabAppend;
			}
			txtIncludeExt.auto_List = new List<string>();
			txtExcludeExt.auto_List = new List<string>();
			foreach (eFile ext in data.Extensions)
			{
				txtIncludeExt.auto_List.Add(ext.Ext);
				txtExcludeExt.auto_List.Add(ext.Ext);	
			}
		}
		#endregion

		#endregion

		#region Change Tab
		private void tbcOptions_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			TabItem mode = (TabItem)tbcOptions.SelectedItem;
			dontChangeTabFlag = true;

			if (mode.Name == "tabReplace" || mode.Name == "tabCasing") grpBeginEnd.IsEnabled = false;
			else grpBeginEnd.IsEnabled = true;

			//Update Preview & Command Text
			if (mode.Name == "tabAppendText") txtAppendText_TextChanged(txtAppendText, null);
			else if (mode.Name == "tabInsert") tabInsert_TextChanged(null, null);
			else if (mode.Name == "tabReplace") ReplaceTab_TextChanged(null, null);
			else if (mode.Name == "tabRemove") txtRemoveCount_TextChanged(txtRemoveCount, null);
			else if (mode.Name == "tabIncrement") tabIncrement_TextChanged(null, null);
			else if (mode.Name == "tabCasing") tabCasing_Changed(null, null);
		}
		#endregion

		#region Beginning/End CheckChanged
		private void BeginningEnd_CheckChanged(object sender, RoutedEventArgs e)
		{
			if (txtAppendText != null && lblCommandText != null)
			{
				string name = ((TabItem)tbcOptions.SelectedItem).Name;
				if (name == "tabAppend")
					txtAppendText_TextChanged(txtAppendText, null);
				else if (name == "tabInsert")
					tabInsert_TextChanged(null, null);
				else if (name == "tabRemove")
					txtRemoveCount_TextChanged(txtRemoveCount, null);
				else if (name == "tabIncrement")
					tabIncrement_TextChanged(null, null);
			}
		}
		#endregion

		#region txtAppendText_TextChanged
		private void txtAppendText_TextChanged(object sender, TextChangedEventArgs e)
		{
			lblCommandText.Content = "{[filename]:ins(" + (radBeginning.IsChecked.Value ? "0" : "-0") + "," + txtAppendText.Text + ")}";
			lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(), 
				String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : txtFirstFileName.Text, 0), new SpecialChars());
			//txtAppendText.Text = ReplaceInvalidChars(txtAppendText.Text);
		}
		#endregion

		#region InsertTab TextChanged
		private void tabInsert_TextChanged(object sender, TextChangedEventArgs e)
		{
			if (radBeginning != null)
			if (radBeginning.IsChecked.Value)
				lblCommandText.Content = "{[filename]:ins(" + txtInsertIndex.Text + "," + txtInsertText.Text + ")}";
			else
				lblCommandText.Content = "{[filename]:ins(-" + txtInsertIndex.Text + "," + txtInsertText.Text + ")}";

			if (lblPreview != null)
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(),
				String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : Helper.HFile.RemoveExtension(txtFirstFileName.Text), 0), new SpecialChars());
		}
		#endregion

		#region ReplaceTab TextChanged
		private void radReplaceOptions_Checked(object sender, RoutedEventArgs e)
		{
			ReplaceTab_TextChanged(null, null);
		}
		private void ReplaceTab_TextChanged(object sender, TextChangedEventArgs e)
		{
			string firstOp = "first";
			if (radReplaceAll != null)
				if (radReplaceAll.IsChecked.Value) firstOp = "all";
				else if (radReplaceLast.IsChecked.Value) firstOp = "last";

			string caseI = "";
			if (radCaseInsensitive != null)
				if (radCaseInsensitive.IsChecked.Value) caseI = ",in";

			if (lblCommandText != null)
				lblCommandText.Content = "{[filename]:rep(" + firstOp + "," + txtReplaceOld.Text + "," + txtReplaceNew.Text + caseI + ")}";

			if (lblPreview != null)
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(),
					String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : HFile.RemoveExtension(txtFirstFileName.Text), 0), new SpecialChars());
		}

		#endregion

		#region RemoveTab_TextChanged
		private void txtRemoveCount_TextChanged(object sender, TextChangedEventArgs e)
		{
			TextBox s = (TextBox) sender;
			String text = s.Text;
			int x = s.SelectionStart;
			int l = s.Text.Length;
			//foreach (Char c in text)
			{
				//if (!Char.IsDigit(c)) s.Text = s.Text.Replace(c.ToString(), "");
			}
			s.SelectionStart = Math.Min(l - s.Text.Length + x, s.Text.Length);

			if (String.IsNullOrEmpty(txtRemoveCount.Text))
			{
				if (radBeginning != null)
					if (radBeginning.IsChecked.Value)
						lblCommandText.Content = "{[filename]:rem(" + txtRemoveIndex.Text + ")}";
					else
						lblCommandText.Content = "{[filename]:rem(-" + txtRemoveIndex.Text + ")}";
			}
			else
			{
				if (radBeginning != null)
					if (radBeginning.IsChecked.Value)
						lblCommandText.Content = "{[filename]:rem(" + txtRemoveIndex.Text + "," + txtRemoveCount.Text + ")}";
					else
						lblCommandText.Content = "{[filename]:rem(-" + txtRemoveIndex.Text + "," + txtRemoveCount.Text + ")}";
			}
			if (lblPreview != null)
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(),
					String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : HFile.RemoveExtension(txtFirstFileName.Text), 0), new SpecialChars());
		}

		#endregion

		#region IncrementTab_TextChanged
		private void tabIncrement_TextChanged(object sender, TextChangedEventArgs e)
		{
			if (radBeginning != null)
			{
				int digits = 0, start = 0;
				int.TryParse(txtIncrementDigits.Text, out digits);
				int.TryParse(txtIncrementStart.Text, out start);

				if (radBeginning.IsChecked.Value)
				{
					lblCommandText.Content = "{[count." + String.Format("{0:" + GetNumDigits(digits) + "}",
																															start) + "]" + txtIncrementSeparator.Text + "[filename]}";
				}
				else
				{
					lblCommandText.Content = "{[filename]" + txtIncrementSeparator.Text + "[count." + String.Format("{0:" + GetNumDigits(digits) + "}",
																															start) + "]}";
				}
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(),
					String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : HFile.RemoveExtension(txtFirstFileName.Text), 0), new SpecialChars());
			}
		}
		public static string GetNumDigits(int num)
		{
			string format = "";
			for (int i = 0; i < num; i++) format += "0";
			return format;
		}
		#endregion

		#region ExpressionTab TextChanged
		private bool addClose = false, removeClose = false;
		private void txtExpression_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
		{
			TextBox exp = (TextBox)sender;
			if (exp.Text.Length > 0 && exp.SelectionStart > 0)
				if (exp.Text[exp.SelectionStart - 1] == '{' && e.Key == System.Windows.Input.Key.Back)
				{
					removeClose = true;
				}
		}
		private void txtExpression_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
		{
			//if (e.Text == "{") addClose = true;
		}
		private void txtExpression_TextChanged(object sender, TextChangedEventArgs e)
		{
			TextBox exp = (TextBox)sender;

			//if (e.Changes.Count >= 0 && exp.Text.Length > 0)
			//{
				//int index = exp.SelectionStart;
				//if (addClose)
				//{
				//  addClose = false;
				//  if (HBasic.CharCount('{', exp.Text) != HBasic.CharCount('}', exp.Text))
				//  {
				//    exp.Text = exp.Text.Insert(index, "}");
				//    exp.SelectionStart = index;
				//    exp.SelectionLength = 0;
				//  }
				//}
				//else if (removeClose && index < exp.Text.Length -1)
				//{
				//  removeClose = false;
				//  exp.Text = exp.Text.Remove(index, 1);
				//  exp.SelectionStart = index;
				//  exp.SelectionLength = 0;
				//}
			//}
			lblCommandText.Content = exp.Text;
			if (fileList.Items.Count == 0)
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(txtExpression.Text,
					String.IsNullOrEmpty(txtFirstFileName.Text) ? "Testfilename" : HFile.RemoveExtension(txtFirstFileName.Text), 0),
																							new SpecialChars());
			else
			{
				FileToRename f = (FileToRename)fileList.Items[0];
				string shortName = f.FileName.Name.Substring(0, f.FileName.Name.Length - f.FileName.Extension.Length);

				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(txtExpression.Text, shortName, 0), new SpecialChars());
			}
		}
		#endregion

		#region tabCasing Changed
		private void tabCasing_Changed(object sender, RoutedEventArgs e)
		{
			tabCasing_TextChanged(null, null);
		}

		private void txtCasingSeparater_GotFocus(object sender, RoutedEventArgs e)
		{
			radCasingCamel.IsChecked = true;
			radCasingAll.IsChecked = false;
		}

		private void tabCasing_TextChanged(object sender, TextChangedEventArgs e)
		{
			string firstOp = "";
			if (radCasingUpper != null && radCasingLower != null)
			{
				if (radCasingUpper.IsChecked.Value) firstOp = "up";
				else if (radCasingLower.IsChecked.Value) firstOp = "lo";
			}

			string second = "";
			if (radCasingFirst != null && radCasingAll != null)
			{
				if (radCasingFirst.IsChecked.Value) second = ",first";
				else if (radCasingAll.IsChecked.Value) second = ",all";
				else second = ",sing";
			}

			string third = "";
			if (second == ",sing" && txtCasingSeparater != null) third = "," + txtCasingSeparater.Text;

			if (lblCommandText != null)
				lblCommandText.Content = "{[filename]:cas(" + firstOp + second + third + ")}";

			if (lblPreview != null)
				lblPreview.Content = Expression.Parse(FileRenamerSystem.ParseExtraCommands(lblCommandText.Content.ToString(),
					String.IsNullOrEmpty(txtFirstFileName.Text) ? "Test file name" : HFile.RemoveExtension(txtFirstFileName.Text), 0), new SpecialChars());
		}
		#endregion

		private void btnClearInclude_Click(object sender, RoutedEventArgs e)
		{
			txtIncludeExt.Text = "";
		}

		private void btnClearExclude_Click(object sender, RoutedEventArgs e)
		{
			txtExcludeExt.Text = "";
		}
	}
}
